package com.yzg.simple.netty.unpacking.unpacking_example.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
   基于Netty TCP 粘包拆包业务场景重现 示例代码
 */
public class NettyTcpServer {

    public static void main(String[] args)throws Exception {
         //如笔记所示,bossGroup 处理连接,workerGroup是处理具体业务的
        // 理解为,bossGroup 接项目,workerGroup做项目 两个都是无限循环
        //  同时两个都是线程池,每一个线程持有NioEventLoop 对应的selector ...
        // 默认初始化的NioEventLoop 是 cpu核数 *2 ,也可以指定
        //如果多客户端超过了 这个线程数,那么就会复用线程,从第一个NioEventLoop 开始
        EventLoopGroup bossGroup =  new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //ServerBootstrap 是对服务端启动进行配置的
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //加入组信息
            serverBootstrap.group(bossGroup, workerGroup)

                    //设置服务器端Channel(通道)对象
                    .channel(NioServerSocketChannel.class)

                    //设置线程对象连接个数
                    .option(ChannelOption.SO_BACKLOG, 128)

                    //设置保持活动来连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE, true)

                    //添加Handler 处理器
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //不是同一个selector 持有的channel 相关之间的通讯的思路,维护一个集合
                            // 在这个集合中找到对应的客户端信息,进行业务操作
                            // 管道(pipeline) 和通道(channel) 是互相包含关系
                            ChannelPipeline pipeline = ch.pipeline();
                             //添加protobuf 解码器
                            pipeline.addLast(new ServerHandler());

                        }
                    });
            //同步器 监听端口,此时进行阻塞
            ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
            //关闭连接
            channelFuture.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}
